﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Security;
using System.Security.Cryptography;
using System.Text;

namespace CBlock
{
    public static class BlockGenerator
    {
        public static List<Block> _blockChain=new List<Block>();

        /// <summary>
        /// 计算区块 HASH 值
        /// </summary>
        /// <param name="block">区块实例</param>
        /// <returns>计算完成的区块散列值</returns>
        public static string CalculateHash(Block block)
        {
            string calcuationStr = $"{block.Index}{block.TimeStramp}{block.PM}{block.PrevHash}";
            SHA256 sha256=SHA256.Create();
            byte[] sha256Bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(calcuationStr));
            StringBuilder sha256Builder=new StringBuilder();
            foreach (var byteSha256Byte in sha256Bytes)
            {
                sha256Builder.Append(byteSha256Byte.ToString("x2"));
            }
            return sha256Builder.ToString();
        }

        public static Block GenrateBlock(Block oldBlock, int pm)
        {
            var newBlock=new Block()
            {
                Index = oldBlock.Index+1,
                TimeStramp = CalcutateCurrentTimeUTC(),
                PM = pm,
                PrevHash = oldBlock.Hash
            };
            newBlock.Hash = CalculateHash(newBlock);
            return newBlock;
        }
        /// <summary>
        /// 检验区块是否有效
        /// </summary>
        /// <param name="newBlock">新生成的区块数据</param>
        /// <param name="oldBlock">旧的区块数据</param>
        /// <returns>有效返回 TRUE，无效返回 FALSE</returns>
        public static bool IsBlockValid(Block newBlock, Block oldBlock)
        {
            if (oldBlock.Index + 1 != newBlock.Index) return false;
            if (oldBlock.Hash != newBlock.PrevHash) return false;
            if (CalculateHash(newBlock) != newBlock.Hash) return false;
            return true;
        }
        /// <summary>
        /// 如果新的区块链比当前区块链更新，则切换当前区块链为最新区块链
        /// </summary>
        /// <param name="newBlockChain">新的区块链</param>
        public static void SwithChain(List<Block> newblockChain)
        {
            if (newblockChain.Count > _blockChain.Count)
            {
                _blockChain = newblockChain;
            }
        }

        public static string CalcutateCurrentTimeUTC()
        {
            DateTime startTime=new DateTime(1970,1,1,0,0,0);
            DateTime nowTime=DateTime.Now;
            long unixTime = (long) Math.Round((nowTime - startTime).TotalMilliseconds, MidpointRounding.AwayFromZero);
            return unixTime.ToString();

        }
    }
}